using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Net;
using Geekeradmin.Authorize;

using Geekeradmin.Entitys;
using Publicuse.Interface;
using Publicuse.Util;
using Publicuse.Entity;

namespace Geekeradmin.Filters
{
    /// <summary>
    /// ---------------------可以处理到的异常-----------
    /// Action出现没有处理的异常
    /// Service层的异常
    /// 其他Filter中发生的异常(有的能捕捉有的不能捕捉)
    /// 控制器构造函数出现异常
    /// 
    /// </summary>
    public class CustomException : Attribute, IExceptionFilter
    {
        private readonly ILogger<CustomException> logger;
        private readonly IModelMetadataProvider _IModelMetadataProvider;
        private readonly IMySqlSugarService mySqlSugar;

        public CustomException(ILogger<CustomException> logger,IModelMetadataProvider modelMetadataProvider, IMySqlSugarService mySqlSugar)
        {
            this.logger = logger;
            this._IModelMetadataProvider = modelMetadataProvider;
            this.mySqlSugar = mySqlSugar;
        }

        public void OnException(ExceptionContext context)
        {
            if (context.ExceptionHandled == false)
            {
                var queryurl = context.HttpContext.Request.Path; // API请求地址
                string param = string.Empty;
                var paramsdata = context.HttpContext.GetParams();
                var querytype = context.HttpContext.Request.Method; // 请求方式
                querytype = "拦截";
                var querydata = string.Empty; // 请求参数
                var queryheader = context.HttpContext.Request.Headers.ToList();
                var loginUserCode = HttpContextExtendBase.GetLoginCode();
                if (string.IsNullOrEmpty(loginUserCode))
                {
                    var result = new CommonResult()
                    {
                        code = (int)ImplementResult.Nopermissiontooperate,
                        msg = ImplementResult.Nopermissiontooperate.GetRemark()
                    };
                    context.Result = new JsonResult(result);
                }
                var headers = HttpContextExtendBase.Current.Request.Headers;
                if (headers.ContainsKey("X-Forwarded-For"))
                {
                  HttpContextExtendBase.Current.Connection.RemoteIpAddress = IPAddress.Parse(
                    headers["X-Forwarded-For"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries)[0]
                  );
                }
                if (headers.ContainsKey("X-Forwarded-For"))
                {
                  HttpContextExtendBase.Current.Connection.RemoteIpAddress = IPAddress.Parse(
                    headers["X-Forwarded-For"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries)[0]
                  );
                }
                var remoteIp =
                  LogClass.GetIPAddress()
                  + "|"
                  + headers["X-Real-IP"].ToString()
                  + "|"
                  + headers["X-Forwarded-For"].ToString();
                if (string.Compare(remoteIp, "::1", true) == 0)
                {
                  remoteIp = HttpContextExtendBase.Current.Connection.LocalIpAddress.MapToIPv4()?.ToString();
                }
                if (remoteIp.Split(':').Length >= 3)
                {
                  remoteIp = remoteIp.Split(':')[3];
                }
                if (!string.IsNullOrEmpty(remoteIp))
                {
                  remoteIp = remoteIp.Replace("unknow", "").Replace("|", "");
                }
                var RemoteIpAddress = HttpContextExtendBase.Current.Connection.RemoteIpAddress;
                var ipaddress = string.Empty;
                var newripad = RemoteIpAddress.ToString();
                if (!string.IsNullOrEmpty(newripad))
                {
                  if (string.Compare(newripad, "::1", true) != 0)
                  {
                    ipaddress = $"{remoteIp + "|" + RemoteIpAddress}";
                  }
                  else
                  {
                    ipaddress = remoteIp;
                  }
                }
                else
                {
                  ipaddress = remoteIp;
                }
                if (!queryurl.Value.ToLower().Contains("import") && !queryurl.Value.ToLower().Contains("upload") && !queryurl.Value.ToLower().Contains("getfilepath"))
                {
                    querydata = context.HttpContext.GetParams(); // 请求参数           
                }
                else
                {
                    querydata = "导入/上传文件数据";
                }
                var content = "请求类型【" + querytype + "】，请求接口【" + queryurl + "】，请求参数【" + querydata + "】，请求头【" + JsonUtil.ToJson(queryheader) + "】";
                Log log = new Log()
                {
                    ipaddress = ipaddress,
                    lmodule = "异常统计",
                    ltype = querytype,
                    luser = HttpContextExtendBase.GetLoginCode(),
                    lsuccess = 1,
                    status = 1,
                    lrole = HttpContextExtendBase.GetLoginrName(),
                    lcontent=content + "，异常信息【" + context.Exception.Message +"|"+context.Exception.StackTrace+ "】"
                };
                this.mySqlSugar.Insert<Log>(log, out var msg);
                //在这里就开始处理异常--还是要响应结果给客户端
                //1.页面展示
                //2.包装成一个JSON格式
                if (IsAjaxRequest(context.HttpContext.Request)) //判断是否是Ajax请求--JSON
                {
                    //JSON返回
                    context.Result = new JsonResult(new
                    {
                        Succeess = false,
                        Message = context.Exception.Message
                    });  
                    context.HttpContext.Response.Redirect("/api/Student/Fail?message=" + context.Exception.Message);
                }
                else
                {
                    //返回页面
                    //ViewResult result = new ViewResult { ViewName = "~/Views/Shared/Error.cshtml" };
                    //result.ViewData = new ViewDataDictionary(_IModelMetadataProvider, context.ModelState);
                    //result.ViewData.Add("Exception", context.Exception);
                    CommonResult result = new CommonResult()
                    {
                        code = (int)CodeResult.exception,
                        msg = $"{context.Exception.Message}"
                    };
                    HttpContextExtendBase.Current.Response.Redirect("/api/Menu/Fail");
                    HandleBlockedResult.result = result;
                    context.Result = new JsonResult(result); //断路器---只要对Result赋值--就不继续往后了； 
                }
                this.logger.LogError(context.Exception.Message);
                context.ExceptionHandled = true;//表示当前异常被处理过
            }
        }

        private bool IsAjaxRequest(HttpRequest request)
        {
            //HttpWebRequest httpWebRequest = null;
            //httpWebRequest.Headers.Add("X-Requested-With", "XMLHttpRequest"); 
            string header = request.Headers["X-Requested-With"];
            return "XMLHttpRequest".Equals(header);
        }
    }
}
